<HTML>
<HEAD>
   <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
   <META NAME="Author" CONTENT="Joshua Neal">
   <META NAME="Description" CONTENT="Pure VGA/SVGA hardware programming (registers, identification, and other low-level stuff.)">
   <META NAME="KeyWords" CONTENT="VGA SVGA hardware video programming">
   <TITLE>VGA/SVGA Video Programming--Color Regsters</TITLE>
</HEAD>
<BODY>

<UL>
<CENTER><A HREF="../home.htm">Home</A> <A HREF="vga.htm#register">Back</A>&nbsp;
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
Page</B></CENTER>

<CENTER>Color Registers</CENTER>

<CENTER>
<HR WIDTH="100%"></CENTER>
</UL>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The Color Registers in the standard
VGA provide a mapping between the palette of between 2 and 256 colors to
a larger 18-bit color space. This capability allows for efficient use of
video memory while providing greater flexibility in color choice. The standard
VGA has 256 palette entries containing six bits each of red, green, and
blue values. The palette RAM is accessed via a pair of address registers
and a data register. To write a palette entry, output the palette entry's
index value to the <A HREF="#3C8">DAC Address Write Mode Register</A> then
perform 3 writes to the <A HREF="#3C9">DAC Data Register</A>, loading the
red, green, then blue values into the palette RAM. The internal write address
automatically advances allowing the next value's RGB values to be loaded
without having to reprogram the <A HREF="#3C8">DAC Address Write Mode Register.&nbsp;
This</A> allows the entire palette to be loaded in one write operation.
To read a palette entry, output the palette entry's index to the <A HREF="#3C7W">DAC
Address Read Mode Register</A>. Then perform 3 reads from the <A HREF="#3C9">DAC
Data Register</A>, loading the red, green, then blue values from palette
RAM. The internal write address automatically advances allowing the next
RGB values to be written without having to reprogram the <A HREF="#3C7W">DAC
Address Read Mode Register</A>.

<P><A NAME="note"></A>Note: I have noticed some great variance in the actual
behavior of these registers on VGA chipsets. The best way to ensure compatibility
with the widest range of cards is to start an operation by writing to the
appropriate address register and performing reads and writes in groups
of 3 color values. While the automatic increment works fine on all cards
tested, reading back the value from the <A HREF="#3C8">DAC Address Write
Mode Register</A> may not always produce the expected result. Also interleaving
reads and writes to the <A HREF="#3C9">DAC Data Register</A> without first
writing to the respected address register may produce unexpected results.
In addition, writing values in anything other than groups of 3 to the <A HREF="#3C9">DAC
Data Register</A> and then performing reads may produce unexpected results.
I have found that some cards fail to perform the desired update until the
third value is written.
<UL>
<LI>
Port 3C8h -- <A HREF="#3C8">DAC Address Write Mode Register</A></LI>

<LI>
Port 3C7h -- <A HREF="#3C7W">DAC Address Read Mode Register</A></LI>

<LI>
Port 3C9h -- <A HREF="#3C9">DAC Data Register</A></LI>

<LI>
Port 3C7h -- <A HREF="#3C7R">DAC State Register</A></LI>
</UL>
&nbsp;
<TABLE BORDER WIDTH="600" CELLPADING="2" >
<CAPTION ALIGN=TOP><A NAME="3C8"></A><B>DAC Address Write Mode Register
(Read/Write at 3C8h)</B></CAPTION>

<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>

<TD WIDTH="75">6</TD>

<TD WIDTH="75">5</TD>

<TD WIDTH="75">4</TD>

<TD WIDTH="75">3</TD>

<TD WIDTH="75">2</TD>

<TD WIDTH="75">1</TD>

<TD WIDTH="75">0</TD>
</TR>

<TR ALIGN=CENTER VALIGN=CENTER>
<TD COLSPAN="8" WIDTH="600">DAC Write Address</TD>
</TR>
</TABLE>
&nbsp;
<UL>
<LI>
<B>DAC Write Address</B></LI>

<BR>Writing to this register prepares the DAC hardware to accept writes
of data to the <A HREF="#3C9">DAC Data Register</A>. The value written
is the index of the first DAC entry to be written (multiple DAC entries
may be written without having to reset the write address due to the auto-increment.)
Reading this register returns the current index, or at least theoretically
it should. However it is likely the value returned is not the one expected,
and is dependent on the particular DAC implementation. (See <A HREF="#note">note</A>
above)</UL>
&nbsp;
<TABLE BORDER WIDTH="600" CELLPADING="2" >
<CAPTION ALIGN=TOP><A NAME="3C7W"></A><B>DAC Address Read Mode Register
(Write at 3C7h)</B></CAPTION>

<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>

<TD WIDTH="75">6</TD>

<TD WIDTH="75">5</TD>

<TD WIDTH="75">4</TD>

<TD WIDTH="75">3</TD>

<TD WIDTH="75">2</TD>

<TD WIDTH="75">1</TD>

<TD WIDTH="75">0</TD>
</TR>

<TR ALIGN=CENTER VALIGN=CENTER>
<TD COLSPAN="8" WIDTH="600">DAC Read Address</TD>
</TR>
</TABLE>
&nbsp;
<UL>
<LI>
<B>DAC Read Address</B></LI>

<BR>Writing to this register prepares the DAC hardware to accept reads
of data to the <A HREF="#3C9">DAC Data Register</A>. The value written
is the index of the first DAC entry to be read (multiple DAC entries may
be read without having to reset the write address due to the auto-increment.)</UL>
&nbsp;
<TABLE BORDER WIDTH="600" CELLPADING="2" >
<CAPTION ALIGN=TOP><A NAME="3C9"></A><B>DAC Data Register (Read/Write at
3C9h)</B></CAPTION>

<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>

<TD WIDTH="75">6</TD>

<TD WIDTH="75">5</TD>

<TD WIDTH="75">4</TD>

<TD WIDTH="75">3</TD>

<TD WIDTH="75">2</TD>

<TD WIDTH="75">1</TD>

<TD WIDTH="75">0</TD>
</TR>

<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75"></TD>

<TD WIDTH="75"></TD>

<TD COLSPAN="6" WIDTH="450">DAC Data</TD>
</TR>
</TABLE>
&nbsp;
<UL>
<LI>
<B>DAC Data</B></LI>

<BR>Reading or writing to this register returns a value from the DAC memory.
Three successive I/O operations accesses three intensity values, first
the red, then green, then blue intensity values. The index of the DAC entry
accessed is initially specified by the <A HREF="#3C7W">DAC Address Read
Mode Register</A> or the <A HREF="#3C8">DAC Address Write Mode Register</A>,
depending on the I/O operation performed. After three I/O operations the
index automatically increments to allow the next DAC entry to be read without
having to reload the index. I/O operations to this port should always be
performed in sets of three, otherwise the results are dependent on the
DAC implementation. (See <A HREF="#note">note</A> above)</UL>
&nbsp;
<TABLE BORDER WIDTH="600" CELLPADING="2" >
<CAPTION ALIGN=TOP><A NAME="3C7R"></A><B>DAC State Register (Read at 3C7h)</B></CAPTION>

<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>

<TD WIDTH="75">6</TD>

<TD WIDTH="75">5</TD>

<TD WIDTH="75">4</TD>

<TD WIDTH="75">3</TD>

<TD WIDTH="75">2</TD>

<TD WIDTH="75">1</TD>

<TD WIDTH="75">0</TD>
</TR>

<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75"></TD>

<TD WIDTH="75"></TD>

<TD WIDTH="75"></TD>

<TD WIDTH="75"></TD>

<TD WIDTH="75"></TD>

<TD WIDTH="75"></TD>

<TD COLSPAN="2" WIDTH="150">DAC State</TD>
</TR>
</TABLE>
&nbsp;
<UL>
<LI>
<B>DAC State</B></LI>

<BR>This field returns whether the DAC is prepared to accept reads or writes
to the <A HREF="#3C9">DAC Data Register</A>. In practice, this field is
seldom used due to the DAC state being known after the index has been written.
This field can have the following values:
<UL>
<LI>
00 -- DAC is prepared to accept reads from the <A HREF="#3C9">DAC Data
Register</A>.</LI>

<LI>
11 -- DAC is prepared to accept writes to the <A HREF="#3C9">DAC Data Register</A>.</LI>
</UL>
</UL>


<P>Notice: All trademarks used or referred to on this page are the property
of their respective owners.
<BR>All pages are Copyright &copy; 1997, 1998, J. D. Neal, except where
noted. Permission for utilization and distribution is subject to the terms
of the <A HREF="license.htm">FreeVGA Project Copyright License</A>.
</BODY>
</HTML>
